﻿using Microsoft.Extensions.DependencyModel;
using Serilog;
using System.Reflection;
using System.Runtime.Loader;

#nullable disable

namespace MyCompany.MyProject.Common.Core
{
    /// <summary>
    /// 运行时扩展类
    /// </summary>
    public static class RuntimeExtension
    {
        /// <summary>
        /// 获取项目程序集、排除所有的系统程序集（Microsoft.***、System.***等）、Nuget 下载包
        /// </summary>
        /// <returns></returns>
        public static IList<Assembly> GetAllAssemblies()
        {
            var list = new List<Assembly>();
            var deps = DependencyContext.Default;
            // 只加载项目中的程序集 排除所以系统程序集、Nuget下载包
            var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type == "project");

            foreach (var lib in libs)
            {
                try
                {
                    var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
                    list.Add(assembly);
                }
                catch (Exception e)
                {
                    Log.Debug(e, "GetAllAssemblies Exception:{ex}", e.Message);
                }
            }
            return list;
        }

        /// <summary>
        /// 根据名称获取程序集
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        public static Assembly GetAssembly(string assemblyName)
        {
            return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
        }

        /// <summary>
        /// 获取所有的类型
        /// </summary>
        /// <returns></returns>
        public static IList<Type> GetAllTypes()
        {
            var list = new List<Type>();
            foreach (var assembly in GetAllAssemblies())
            {
                var typeInfos = assembly.DefinedTypes;
                foreach (var typeInfo in typeInfos)
                {
                    list.Add(typeInfo.AsType());
                }
            }
            return list;
        }

        /// <summary>
        /// 通过程序集名称获取所有的类型
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        public static IList<Type> GetTypesByAssembly(string assemblyName)
        {
            var list = new List<Type>();
            var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
            var typeInfos = assembly.DefinedTypes;
            foreach (var typeInfo in typeInfos)
            {
                list.Add(typeInfo.AsType());
            }
            return list;
        }

        /// <summary>
        /// 获取使用指定接口的实现类
        /// </summary>
        /// <param name="typeName"></param>
        /// <param name="baseInterfaceType"></param>
        /// <returns></returns>
        public static Type GetImplementType(string typeName, Type baseInterfaceType)
        {
            return GetAllTypes().FirstOrDefault(t =>
             {
                 if (t.Name == typeName && t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
                 {
                     var typeInfo = t.GetTypeInfo();
                     return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;
                 }
                 return false;
             });
        }

    }
}
